﻿ 
 // Este programa captura dos valores en coma flotante (utilizando punto como separador de decimales) separados por una coma
 // del puerto serie a 9600 baudios. El primero corresponde al angulo de alabeo (ROLL),
 // el segundo mide el angulo de cabeceo (PITCH). De momento no voy a tener en cuenta el angulo de guiñada
 // Voy a intentar dibujar el equivalente a un horizonte artificial,
 // por lo que el comportamiento del horizonte será justo el contrario al del vehículo. Ojo, los ángulos están en radianes.
 
 // Javier Castellanos
 // 17-6-2012
 // He utilizado algunos ejemplos de processing para ver como lee del puerto serie.

 
 import processing.serial.*;
 
 Serial myPort;        // The serial port
 int radio = 210;         // Extremos de la línea y corrección vertical
 
 void setup () {
 // set the window size:
 size(700, 700);        
 
 // Lista de puertos serie disponibles. Lo saco, porque puedo ejecutar el programa en distintos ordenadores
println(Serial.list());
 // En mi ordenador de sobremesa, es el puerto 1, mientras que en el portatil es el puerto 0
 myPort = new Serial(this, Serial.list()[1], 9600);
 // generamos un serialEvent() cuando se recibe el código de fin de línea:
 myPort.bufferUntil('\n');
 // Fondo negro de la pantalla
 background(0);
 }
 void draw () {
 // No vamos a hacer nada aquí, sino que todo ocurre en el apartado de serial event
 }
 
 void serialEvent (Serial myPort) {
 // capturamos la cadena
 String inString = myPort.readStringUntil('\n');
 
 if (inString != null) {
   // No voy a quitar ningún espacio de la cadena, porque desde Arduino tengo controlado lo que envio
   // inString = trim(inString);
   //Separamos la cadena en los dos angulos y lo convertimos en coma flotante
   float[] angulo = float (split (inString,','));
   
   // Imprimo los valores simplemente como ayuda para el debug. Se podría comentar
   //Angulo de alabeo (ROLL)
   print(angulo[0]);
   print("  ");
   // Angulo de cabeceo (PITCH)
   println(angulo[1]);
   
   angulo[0]=-angulo[0];
   angulo[1]=-angulo[1];
   v_pintarCielo(angulo);
   v_pintarTierra(angulo);
   v_pintarFondo();
   //v_pintarBrujula(angulo);
   //v_pintarBrujula2(angulo);
   
   
   }
 }
 
 
 
 
 
 void v_pintarCielo (float[] angulo)
 {
   noStroke();
   fill(0,0,255);
   rect(0,0,width,height);
 }
 
 
 //SE pinta la parte de tierra
 void v_pintarTierra (float[] angulo)
 {
   
  int widthG = 600;
  float y=radio*sin(angulo[1]);
  
  pushMatrix();
    translate(width/2, height/2); 
    rotate(angulo[0]);
    translate(0,y);
    noStroke();
    fill(190,50,75);
    rect(-widthG/2, 0, widthG, 400);
  popMatrix();
  
  stroke(255,255,255);
  strokeWeight(2);
  line(height/2-radio,height/2, height/2 + radio,height/2);
 }
 
 
//Pintamos el fondo de negro 
void v_pintarFondo ()
{
  stroke(0,0,0);
  fill(0,0,0);
  rect(0,0, width, (height-radio*2)/2 -5);
  rect(0,   radio*2 + (height-radio*2)/2 +5, width, (height-radio*2)/2);
  rect(0,0,  (width-radio*2)/2 -5, height);
  rect(radio*2 + (width-radio*2)/2 +5, 0,   (width-radio*2)/2, width);
  noFill();
  strokeWeight(40);
  ellipseMode(CENTER);
  
  for  (int i=1;  i < 201; i=i+10){
    ellipse ( width/2,width/2, radio*2+i,radio*2+i);
  }
 
}


//Puntos Cardinales en la parte inferior de la pantalla
void v_pintarBrujula2(float[] angulo)
{
  String [] puntosCardinales ={"N","NO","O","SO","S","SE","E","NE"};
  int angulo_ = (int)degrees(angulo[2])-45;
  int anguloTrabajo = 0;
  
  int y = height-10;
  float x = width/2 - width/3;
  int tamano = 5;
  int puntoCardinal = 0;
  float espacio =  5;
  
  for (int index=0; index<90; angulo_=angulo_+1, index++, x = x + espacio)
  {
    //Se comprueba que el angulo no sea mayor de 360 ni menor de 0. Este es para poder hacer correctamente las operaciones
    if (angulo_<0)
    {
      anguloTrabajo = angulo_ + 360;
    }
    else if (angulo_ == 360.0)
    {
      anguloTrabajo = 0; 
    }
    else
    {
      anguloTrabajo = angulo_;
    }
    println (anguloTrabajo);
    
    //Si es un punto multiplo de 45º es uno de los importantes se pinta el nombre
    if(anguloTrabajo%45==0)
    {
      puntoCardinal = (int)anguloTrabajo/45;
      tamano = 10;
       text(puntosCardinales[puntoCardinal],
         x - 4, 
         y-2*tamano); 
    } 
    else
    {
      tamano = 5;
    } 
    
    line (x, y, x, y-tamano );
  }  
}


//Puntos cardinales alrededor del horizonte artificial
void v_pintarBrujula(float[] angulo)
{
    fill(255,255,255);
    stroke(255,255,255);
   strokeWeight(2);
   float puntoX = 0;
   float puntoY = 0;
   int multiplicador = 3;
   int multiplicador2 = 10;
   int multiplicadorTextoY =15;
   int multiplicadorTextoX =15;
   String [] puntosCardinales ={"E","SE","S","SO","O","NO","N","NE"};
   int index= 0;
   int indexTexto = 0;
   
   pushMatrix();
     translate (width/2,height/2);
     rotate (angulo[2]);
     
     for (int angulo_=0 ; angulo_<360; angulo_=angulo_+15, index++)
     {
       puntoX = radio*cos(radians(angulo_));  
       puntoY =  radio*sin(radians(angulo_));
       
       //Si es una línea de uno de los puntos cardinales se pinta el nombre
       if(index%3==0)
       {
         multiplicador = 0;
         multiplicador2 = 14; 
         text(puntosCardinales[indexTexto++],
             puntoX+multiplicadorTextoX*cos(radians(angulo_)) - 4, 
             puntoY+multiplicadorTextoY*sin(radians(angulo_))); 
       }
       else
       {
         multiplicador = 5;
         multiplicador2 = 10; 
       }
       
       line (puntoX-multiplicador*cos(radians(angulo_)), 
             puntoY-multiplicador*sin(radians(angulo_)), 
             puntoX-multiplicador2*cos(radians(angulo_)), 
             puntoY-multiplicador2*sin(radians(angulo_)));
     }
   popMatrix();
    
    
    
   
  
   //200+(200*sin(roll-pitch)),
   // Dibujo la línea de horizonte
   stroke(127,34,255);
   //line(x0, y0, x1, y1);
   // Dibujo la línea del avion
   stroke(127,200,255);
   //line(0, 200, width, 200);
} // Fin del fichero
